package smallfrench.moteur.noeuds;

import java.util.ArrayList;

import smallfrench.moteur.biblio.RBooleen;
import smallfrench.moteur.biblio.RClasse;
import smallfrench.moteur.biblio.err.ErreurClasse;
import smallfrench.moteur.biblio.err.ErreurRien;
import smallfrench.moteur.interp.Portee;
import smallfrench.moteur.interp.RObjet;
import smallfrench.moteur.interp.err.RException;
import smallfrench.moteur.lexer.lexemes.Lexeme;

/**
 * Condition (== "if")<br>
 * <br>
 * <pre>
 * si (cond)
 *     instruction
 * ousi (cond)
 *     instruction
 * ...
 * sinon
 *     instruction
 * </pre>
 * @author antoine1023
 *
 */
public class NSi extends Noeud {

	private final Noeud[] noeudsConditions;
	private final Noeud[] noeudsVrais;

	/**
	 * Nullable
	 */
	private Noeud noeudFaux;

	/**
	 * 
	 * @param t
	 * @param noeudsConditions
	 * @param noeudsVrais
	 * @param noeudFaux
	 */
	public NSi(Lexeme t,
			ArrayList<Noeud> noeudsConditions,
			ArrayList<Noeud> noeudsVrais,
			Noeud noeudFaux) {

		super(t);

		this.noeudsConditions = noeudsConditions.toArray(
				new Noeud[noeudsConditions.size()]);

		this.noeudsVrais = noeudsVrais.toArray(new Noeud[noeudsVrais.size()]);

		if (noeudsConditions.size() != noeudsVrais.size()) {
			throw new IllegalArgumentException("La taille de " +
					"noeudsConditions doit être égale à la taille de " +
					"noeudsVrais");
		}

		this.noeudFaux = noeudFaux;
	}

	@Override
	public RObjet evaluer(Portee pile) {
		for (int i = 0; i < noeudsConditions.length; i++) {

			Noeud noeudCondition = noeudsConditions[i];

			RObjet condition = noeudCondition.evaluer(pile);

			ErreurRien.assertion(noeudCondition.lexeme.debut, condition);

			if (!(condition instanceof RBooleen)) {

				ErreurClasse e = new ErreurClasse(
						condition, RClasse.CLASSE);

				e.ajouterPosition(noeudCondition.lexeme.debut);

				throw new RException(e);

			}

			if (((RBooleen)condition).valeur) {
				Noeud noeudVrai = noeudsVrais[i];
				return noeudVrai.evaluer(pile);
			}
		}
		if (noeudFaux != null) {
			return noeudFaux.evaluer(pile);
		}
		return null;
	}

	@Override
	public String toString() {

		String s = "";
		boolean debut = true;

		for (int i = 0; i < noeudsConditions.length; i++) {
			Noeud cond = noeudsConditions[i];
			Noeud n = noeudsVrais[i];
			if (debut) {
				s += "si (";
				debut = false;
			} else {
				s += "ousi (";
			}
			s += cond + ") " + n + "\n";
		}

		if (noeudFaux != null) {
			s += "sinon " + noeudFaux;
		}

		return s;
	}

}
